package model.mwgde;

import java.util.ArrayList;
import java.util.List;

import model.PartProcess;
import model.auxillary.Parameter;
import model.auxillary.ParameterCollection;
import model.auxillary.ParameterList;
import model.auxillary.ParameterList.ParameterType;

/**
 * The class {@code Drilling} models a drilling process.
 * @author Oliver Eckstein
 *
 */
public class Drilling extends MWGDE {

	/**
	 * To create a new instance of a {@code Drilling} process.
	 * @param name the process' name.
	 */
	public Drilling(String name) {
		super(name, "Drilling_" + getManuMethodsCreatedCount());
		super.addParameters();		
		addParameters();
		addTool();
		addPartProcess();
		setMethod(Method.DRILLING);
        subType = SubType.DRILLING;    
	}

	@Override
	public ParameterList addPartProcess() throws IndexOutOfBoundsException {
		if (partProcesses.size() == MAX_PART_PROCESSES) {
			throw new IndexOutOfBoundsException("Maximum number of allowed "
					+ "part processes is reached.");
		}
		PartProcess newProcess = new PartProcessDrilling(
				this,
				"PP_" + getPartProCount() + "_" + this.getID(),
				getPartProCount(),
				"Prozessbeschreibung");
		partProcesses.add(newProcess);		
		return newProcess.getParameters();
	}

	@Override
	public ParameterCollection addTool() {
		int toolIndex = parameters.getTools().size();
		List<Parameter> newParams = new ArrayList<Parameter>();		
		newParams.add(new Parameter(
				"Anzahl Schneiden",
				"z_s," + toolIndex,
				"<html>z<sub>s," + toolIndex + "</sub></html>",
				"<html>[1]</html>",
				true,
				this));
		
		newParams.add(new Parameter(
				"Nenndurchmesser",
				"d_" + toolIndex,
				"<html>d<sub>" + toolIndex + "</sub></html>",
				"[mm]",
				true,
				this));
		
		newParams.add(new Parameter(
				"Spanwinkel",
				"gamma_" + toolIndex,
				"<html>&gamma;<sub>" + toolIndex + "</html>",
				"<html>[&deg;]</html>",
				true,
				this));
		
		newParams.add(new Parameter(
				"Stumpfungsfaktor",
				"f_st," + toolIndex,
				"<html>f<sub>st," + toolIndex + "</sub></html>",
				"[1]",
				true,
				this));
		
		newParams.add(new Parameter(
				"Spitzenwinkel",
				"sigma_" + toolIndex,
				"<html>&sigma;<sub>" + toolIndex + "</sub></html>",
				"[1]",
				true,
				this));		
		return parameters.addTool(newParams);
	}

	@Override
	public void calculate() {
		error = false;
    	aborted = false;
    	
    	double eAct = getParameter(
				"E_ist", ParameterType.PROCESS_PARAMETER).getValue();
    	double eta = getParameter(
				"eta_ges", ParameterType.PROCESS_PARAMETER).getValue();
    	setRelCutterAngle();
    	double gamma_0 = getParameter(
				"gamma_0", ParameterType.DEPENDENT_PARAMETER).getValue();
    	double z = getParameter(
				"z", ParameterType.MATERIAL_PARAMETER).getValue();
    	 double k_c11 = getParameter(
					"k_c11", ParameterType.MATERIAL_PARAMETER).getValue();     	
     	
     	for (PartProcess partProcess : partProcesses) {    		
    		PartProcessDrilling ppd = (PartProcessDrilling) partProcess;
    		double t = partProcess.getParameter(
					"t", ParameterType.GEOMETRY_PARAMETER).getValue();    
    		double d = partProcess.getParameter(
					"d", ParameterType.TOOL_PARAMETER).getValue();
    		double A = ppd.setMachiningSurface(d, t);
    		double R_m = getParameter("R_m", ParameterType.MATERIAL_PARAMETER)
    				.getValue();
            double eMinPhy = ppd.setPhysMinEnergy(A, R_m, t);            
            double l_pro = ppd.computeProcessLength();
            double V = ppd.computeVolume();
            double n = ppd.getParameter(
            		"n", ParameterType.GEOMETRY_PARAMETER).getValue();
            Double f = partProcess.getParameter(
					"f", ParameterType.GEOMETRY_PARAMETER).getValue();
    		Double v_f = partProcess.getParameter(
					"v_f", ParameterType.GEOMETRY_PARAMETER).getValue();
    		ppd.setFeedAndFeedRate(f, v_f, n);
    		f = partProcess.getParameter(
					"f", ParameterType.GEOMETRY_PARAMETER).getValue();
    		v_f = partProcess.getParameter(
					"v_f", ParameterType.GEOMETRY_PARAMETER).getValue();
    		
            double t_pro = ppd.setTime(l_pro, v_f, true);
            double t_H = ppd.setTime(t, v_f, false);
            double v_c = ppd.setRotatingCuttingSpeed(d, n);
            double h = ppd.computeChippingThickness();
            double f_h = ppd.setFactorChippingThickness(h, z);
            double gamma = ppd.getParameter(
            		"gamma", ParameterType.TOOL_PARAMETER).getValue();
            double f_gamma = ppd.setFactorCutterAngle(gamma, gamma_0);
            double f_sv = ppd.setFactorCuttingMaterialSpeed(v_c);
            double f_f = ppd.setFactorForm(d, getMethod());
            double f_st = ppd.getParameter(
            		"f_st", ParameterType.TOOL_PARAMETER).getValue();
            double f_B = getParameter(
            		"f_B", ParameterType.PROCESS_PARAMETER).getValue();
            double factors = f_h * f_gamma * f_sv * f_f *  f_st * f_B;
            double k_c = ppd.setSpecificRelativeCuttingForce(factors, k_c11);
            double Q = ppd.setMrr(V, t_H);
            double P_c = ppd.setCuttingOutput(Q, k_c);
            double eMinTech = ppd.setTechMinEnergy(P_c, t_pro);
            double P = ppd.setOutput(P_c, eta);
            double eMinReal = ppd.setRealMinEnergy(P, t_pro);
            ppd.setPhysEffectivenessPartProcess(eAct, eMinPhy);
            ppd.setTechnEffectivenessPartProcess(eAct, eMinTech);
            ppd.setRealEffectivenessPartProcess(eAct, eMinReal);
     	}
     	double P_c = setCuttingOutput();
     	setOutput(P_c, eta);
     	double eMinPhy = setPhysMinEnergy();
    	double eMinTech = setTechMinEnergy();
    	double eMinReal = setRealMinEnergy();    	
    	setPhysicalEffectiveness(eAct, eMinPhy);
    	setTechnologicalEffectiveness(eAct, eMinTech);
    	setRealEffectiveness(eAct, eMinReal);
    	calculated = true;

	}
	
	@Override
	protected void addParameters() {
		List<Parameter> newParams = new ArrayList<Parameter>();		
		newParams.add(new Parameter(
				"Reibkraftfaktor",
				"f_B",
				"<html>f<sub>B</sub></html>",
				"[1]",
				true,
				this));		

		parameters.addParameters(ParameterType.PROCESS_PARAMETER, newParams);
		
	}
}
